import java.util.concurrent.Executor;
import java.util.concurrent.locks.LockSupport;
import sun.misc.Unsafe;

// java --enable-preview Loom
public class Loom {
	public static void main(String[] args) throws Exception {
		var f = Unsafe.class.getDeclaredField("theUnsafe");
		f.setAccessible(true);
		var U = (Unsafe)f.get(null);
		long OVERRIDE_OFFSET;
		for (long i = 0; ; ) {
			if (U.getBoolean(f, i)) {
				f.setAccessible(false);
				if (!U.getBoolean(f, i)) {
					OVERRIDE_OFFSET = i;
					break;
				}
				f.setAccessible(true);
			}
			if (++i == 32) // should be enough
				throw new UnsupportedOperationException();
		}
		var tb = Thread.ofVirtual();
		f = tb.getClass().getDeclaredField("scheduler");
		U.putBoolean(f, OVERRIDE_OFFSET, true); // f.setAccessible(true);
		f.set(tb, (Executor)Runnable::run);

		var t = new Thread[2];
		t[0] = tb.unstarted(() -> {
			System.out.println("t[0]: begin " + Thread.currentThread()); // 2
			LockSupport.unpark(t[1]);
			LockSupport.park();
			System.out.println("t[0]: end " + Thread.currentThread()); // 5
		});
		t[1] = tb.unstarted(() -> {
			System.out.println("t[1]: begin " + Thread.currentThread()); // 4
			LockSupport.park();
			LockSupport.unpark(t[0]);
			System.out.println("t[1]: end " + Thread.currentThread()); // 6
		});
		System.out.println("main: begin " + Thread.currentThread()); // 1
		t[0].start();
		System.out.println("main: ts[0] started"); // 3
		t[1].start();
		System.out.println("main: ts[1] started"); // 7
		t[0].join();
		System.out.println("main: end " + Thread.currentThread()); // 8
	}
}
